<template>
  <div>
    <p class="btnState">
      <el-tag effect="plain">执行中</el-tag>
      <el-tag effect="plain" type="success">已执行</el-tag>
      <el-tag effect="plain" type="info">未执行</el-tag>
      <el-tag effect="plain" type="danger">结束</el-tag>
      <el-tag effect="plain" type="warning">已跳过</el-tag>
    </p>
    <div id="container" class="container" />
  </div>
</template>

<script>
import { Graph } from '@antv/x6'
import { Scroller } from '@antv/x6-plugin-scroller'
import { register } from '@antv/x6-vue-shape'
import { Snapline } from '@antv/x6-plugin-snapline'
import { FlowNodeType } from '@/flow/config/flowConfig'
import flowNode from './components/flowNode.vue'
import { GetNodeState } from '@/flow/api/flowAudit'
export default {
  components: {
    // eslint-disable-next-line vue/no-unused-components
    Graph,
    // eslint-disable-next-line vue/no-unused-components
    flowNode
  },
  props: {
    logId: {
      type: String,
      default: null
    },
    flowId: {
      type: String,
      default: null
    },
    isLoad: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    theme() {
      return this.$store.getters.theme
    }
  },
  data() {
    return {
      graph: null,
      nodeId: null,
      visible: false,
      status: 0,
      width: null,
      height: null,
      nodes: {},
      source: null
    }
  },
  watch: {
    isLoad: {
      handler(val) {
        if (val) {
          this.initFlow()
        }
      },
      immediate: true
    }
  },
  mounted() {
  },
  methods: {
    async initFlow() {
      const nodes = await GetNodeState(this.logId, this.flowId)
      this.source = nodes
      this.$nextTick(this.init)
    },
    initNode() {
      if (this.source.length > 0) {
        this.source.forEach(e => {
          this.addNode(e)
        })
        this.initLink(this.source)
      }
    },
    initControl() {
      Graph.registerNode(
        'beginNode',
        {
          inherit: 'circle',
          width: 80,
          height: 80,
          attrs: {
            body: {
              strokeWidth: 3,
              stroke: '#909399'
            },
            label: {
              text: '开始',
              fontSize: 16,
              fill: '#000'
            }
          }
        },
        true
      )
      Graph.registerNode(
        'endNode',
        {
          inherit: 'circle',
          width: 80,
          height: 80,
          attrs: {
            body: {
              strokeWidth: 2,
              stroke: '#909399'
            },
            label: {
              text: '结束',
              fontSize: 16,
              fill: '#000'
            }
          }
        },
        true
      )
      register(
        {
          shape: 'flowNode',
          width: 300,
          height: 130,
          component: flowNode
        }
      )
    },
    validateMagne(e) {
      return e.magnet.getAttribute('port-group') === 'bottom'
    },
    getFlowNode(sour) {
      const node = {
        shape: 'beginNode',
        data: {
          id: sour.Id,
          name: sour.NodeName,
          nodeType: sour.NodeType,
          auditType: sour.AuditType,
          show: sour.Show,
          status: sour.Status
        },
        ports: {
          groups: {},
          items: []
        }
      }
      if (sour.NodeType === FlowNodeType.begin.value) {
        node.shape = 'beginNode'
        if (sour.Status === 2) {
          node.attrs = {
            body: {
              strokeWidth: 3,
              stroke: '#43af2b'
            }
          }
        } else if (sour.Status === 1) {
          node.attrs = {
            body: {
              strokeWidth: 3,
              stroke: '#1890ff'
            }
          }
        } else {
          node.attrs = {
            body: {
              strokeWidth: 3,
              stroke: '#ff4949'
            }
          }
        }
        if (sour.Coordinate == null) {
          node.x = (this.width - 80) / 2
          node.y = 100
          this.setCoordinate(sour.Id, node.x, node.y)
        } else {
          node.x = sour.Coordinate.X
          node.y = sour.Coordinate.Y
        }
      } else if (sour.NodeType === FlowNodeType.end.value) {
        node.shape = 'endNode'
        if (sour.Status !== 0) {
          node.attrs = {
            body: {
              strokeWidth: 3,
              stroke: '#ff4949'
            }
          }
        }
        node.x = sour.Coordinate.X
        node.y = sour.Coordinate.Y
      } else if (sour.NodeType === FlowNodeType.subFlow.value) {
        node.shape = 'flowNode'
        node.x = sour.Coordinate.X
        node.y = sour.Coordinate.Y
      } else {
        node.shape = 'flowNode'
        node.x = sour.Coordinate.X
        node.y = sour.Coordinate.Y
      }
      return node
    },
    addNode(sour) {
      const node = this.getFlowNode(sour)
      const flowNode = this.graph.createNode(node)
      const id = this.graph.addNode(flowNode)
      this.nodes[sour.Id] = id
    },
    initLink(routes) {
      if (routes != null && routes.length > 0) {
        routes.forEach(c => {
          if (c.ToNode == null || c.ToNode.length === 0) {
            return
          }
          const sour = {
            cell: this.nodes[c.Id],
            port: 'from'
          }
          c.ToNode.forEach(n => {
            const item = {
              source: sour,
              target: {
                cell: this.nodes[n.NodeId],
                port: 'to'
              },
              data: {
                routeId: n.Id,
                toId: this.nodes[n.NodeId],
                fromId: sour.cell
              },
              tools: [],
              attrs: {
                line: {
                  stroke: '#8f8f8f',
                  strokeWidth: 1
                }
              }
            }
            this.graph.addEdge(item)
          })
        })
      }
    },

    init() {
      if (this.graph == null) {
        this.initControl()
      } else {
        this.graph.dispose()
      }
      this.nodes = {}
      const control = document.getElementById('container')
      let width = 1120
      let height = 600
      if (control.offsetWidth > 1120) {
        width = control.offsetWidth
      }
      if (control.offsetHeight > 600) {
        height = control.offsetHeight
      }
      this.width = width
      this.height = height
      const graph = new Graph({
        container: control,
        width: width,
        height: height,
        resizing: true,
        panning: false,
        background: {
          color: this.theme === 'dark' ? '#1d1e1f' : '#F2F7FA'
        },
        mousewheel: {
          enabled: true,
          modifiers: ['ctrl', 'meta'],
          minScale: 0.5,
          maxScale: 2
        },
        interacting: {
          nodeMovable: true,
          edgeMovable: false,
          magnetConnectable: true
        },
        connecting: {
          snap: true,
          allowBlank: false,
          allowLoop: false,
          allowPort: true,
          allowNode: false,
          allowEdge: false,
          allowMulti: false,
          highlight: false,
          validateMagnet: this.validateMagne,
          validateConnection: this.validateConnection
        },
        highlighting: {
          magnetAvailable: {
            name: 'stroke',
            args: {
              attrs: {
                fill: '#fff',
                stroke: '#A4DEB1',
                strokeWidth: 4
              }
            }
          },
          magnetAdsorbed: {
            name: 'stroke',
            args: {
              attrs: {
                fill: '#fff',
                stroke: '#31d0c6',
                strokeWidth: 4
              }
            }
          }
        }
      })
      graph.use(
        new Snapline({
          enabled: true
        })
      )
      graph.use(
        new Scroller({
          enabled: true
        })
      )
      this.graph = graph
      this.initNode()
    }
  }
}
</script>
<style scoped>
.container {
  width: 100%;
  min-height: 600px;
}
.btnState .el-tag {
    margin-right: 5px;
}
</style>
